/*
 * Copyright (c) Huawei Technologies Co., Ltd. 2021-2022. All rights reserved.
 *
 */

import { FileSet } from '@ohos/hvigor';
import fse from 'fs-extra';
import path from 'path';

import { BuildDirConst } from '../../const/build-directory-const.js';
import { CommonConst } from '../../const/common-const.js';
import { DeviceTypeConst } from '../../const/device-type-const.js';
import { CompileResourceBuildCommandType } from '../../utils/compile-resources-util.js';
import { OhosLogger } from '../../utils/log/ohos-logger.js';
import { AbstractCompileResource } from '../abstract/abstract-compile-resource.js';
import { TaskNames } from '../common/task-names.js';
import { ModuleTargetData } from '../data/hap-task-target-data.js';
import { TargetTaskService } from '../service/target-task-service.js';

import { getTaskRealName } from './hook/legacy-hook-compile-resource.js';
import { LegacyProcessResource } from './legacy-process-resource.js';
import LegacyFATask = TaskNames.LegacyFATask;
import { HarTargetUtil } from '../../utils/har-target-util.js';

/**
 * 老模型的资源编译任务
 *
 * @since 2022/1/20
 */
export class LegacyCompileResource extends AbstractCompileResource {
  protected processProfileTask: string;
  private _log: OhosLogger = OhosLogger.getLogger(LegacyCompileResource.name);

  constructor(taskService: TargetTaskService, entryModuleName?: string) {
    super(taskService, getTaskRealName(LegacyFATask.COMPILE_RESOURCE, entryModuleName));
    this.entryModuleName = entryModuleName;
    this.generateSourceRDir = this.getTaskTempDir(this.targetData, BuildDirConst.R, false);
    this.resConfigFilePath = path.resolve(this.pathInfo.getIntermediatesRes(), entryModuleName ?? '', CommonConst.RES_CONFIG_FILE);
    this.processProfileTask = getTaskRealName({ name: LegacyProcessResource.name }, this.entryModuleName).name;
  }

  declareExecutionCommand(): string {
    return this.getCommand().toString();
  }

  declareInputFiles(): FileSet {
    return this.restoolConfigBuilder.inputFiles.addEntries([this.resConfigFilePath!], {
      isDirectory: false,
    });
  }

  initTaskDepends() {
    this.declareDepends(getTaskRealName({ name: LegacyProcessResource.name }, this.entryModuleName).name);
  }

  protected initHarModuleDepends() {
    const depHarTargets = HarTargetUtil.calDepHarTargets(this.targetService);
    depHarTargets.forEach((targetName, harName) => this.declareDepends(`${targetName}@${LegacyFATask.COMPILE_RESOURCE.name}`, harName));
  }

  async doTaskAction(): Promise<void> {
    await this.compilationProcess(CompileResourceBuildCommandType.FILE, this.targetData);
  }

  async invokeRestool(targetData: ModuleTargetData) {
    if (this.entryModuleName === undefined) {
      await this.executeCommand(this.getCommand(), this._log, () => {
        // 跨设备场景时，将config.json中的deviceType改为纯富设备类型
        if (this.targetData.isSingleDeviceTypeTarget()) {
          return;
        }
        const richDeviceType = this.targetData.getTargetDeviceType().filter((deviceType) => !DeviceTypeConst.LITE_DEVICES.includes(deviceType));

        const liteDeviceType = this.targetData.getTargetDeviceType().filter((deviceType) => DeviceTypeConst.LITE_DEVICES.includes(deviceType));

        const configPath = path.resolve(this.pathInfo.getIntermediatesRes(), this.entryModuleName ?? '', CommonConst.CONFIG_JSON);
        const config = fse.readJsonSync(configPath);
        config.module.deviceType = richDeviceType;

        fse.outputJSONSync(configPath, config, { spaces: '\t' });

        // 如果不需要打bin包，则在res/default/lite目录创建config.json，以提供给构建瘦hap包时使用
        if (this.targetService.needPackBin(targetData)) {
          return;
        }

        const entryName = this.entryModuleName ?? '';
        const liteConfigPath = path.resolve(this.pathInfo.getIntermediatesRes(), entryName, DeviceTypeConst.LITE, CommonConst.CONFIG_JSON);

        config.module.deviceType = liteDeviceType;

        fse.ensureDirSync(path.resolve(this.pathInfo.getIntermediatesLiteSource(), entryName, DeviceTypeConst.LITE));
        fse.outputJSONSync(liteConfigPath, config, { spaces: '\t' });
      });
    } else {
      await this.executeCommand(this.getCommand(), this._log, async () => {
        await this.retainDeviceType(targetData, this.entryModuleName!, this._log);
      });
    }
  }
}
